/*
 * Copyright 2020-2030 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitee.minimalismstyle.fresh.common.core.extra

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.BeanUtils
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import kotlin.reflect.KClass

/**
 * Any扩展
 * @author maoxiaodong
 */

/**
 * 增加日志属性，方便日志处理
 */
val Any.log: Logger
    get() = LoggerFactory.getLogger(this.javaClass)!!


/**
 * 复制属性值给目标对象
 * @param obj 目标对象
 * @return 处理后的目标对象
 */
infix fun <T> Any.copyProperties(obj: T): T {
    BeanUtils.copyProperties(this, obj as Any)
    return obj
}

/**
 * 新建对象并复制属性值给目标对象
 * @param clazz 目标对象KClass
 * @return 目标对象
 */
fun <T : Any> Any.copyProperties(clazz: KClass<T>): T {
    return copyProperties(clazz.java)
}

/**
 * 新建对象并复制属性值给目标对象
 * @param clazz 目标对象java Class
 * @return 目标对象
 */
fun <T : Any> Any.copyProperties(clazz: Class<T>): T {
    val obj: T = clazz.getDeclaredConstructor().newInstance()
    BeanUtils.copyProperties(this, obj)
    return obj
}

/**
 * 获取当前类的指定泛型
 * @param index 第几个泛型
 * @return 泛型 Class
 */
@Suppress("UNCHECKED_CAST")
fun <T> Any.genericTypeFirst(index: Int): Class<T>? {
    val superClass: Type = javaClass.genericSuperclass
    return if (superClass is ParameterizedType) {
        val type: Type = superClass.actualTypeArguments[index]
        type as Class<T>
    } else {
        null
    }

}
